﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Web;
using System.Xml;

namespace TrafficArchives.Client
{
    public class ServiceClient
    {
        private readonly InvokeXFire _proxy;
        private readonly string _licenceKey;

        public ServiceClient()
        {
            var url = ConfigurationManager.AppSettings["XFireUrl"];
            _licenceKey = ConfigurationManager.AppSettings["LicenceKey"];
            _proxy = new InvokeXFire();
            if (!string.IsNullOrEmpty(url))
            {
                _proxy.Url = ConfigurationManager.AppSettings["XFireUrl"];
            }
        }

        public string XmlCondition
        {
            get { return "<?xml version=\"1.0\" encoding=\"GBK\"?><root>{0}</root>"; }
        }

        public string ToXmlField(string fieldName, string value)
        {
            return string.Format("<{0}>{1}</{0}>", fieldName, value);
        }

        /// <summary>
        /// 读取驾驶证信息。
        /// </summary>
        /// <param name="identityNo">身份证号</param>
        /// <param name="archivesNo">档案编号</param>
        /// <returns></returns>
        public 驾驶证信息 GetDrivingLicence (string identityNo, string archivesNo)
        {
            var info = new 驾驶证信息();
            var sb = new StringBuilder();
            if (!string.IsNullOrEmpty(identityNo))
            {
                sb.Append(ToXmlField("sfzmmc", identityNo));
            }
            if (!string.IsNullOrEmpty(archivesNo))
            {
                sb.Append(ToXmlField("dabh", archivesNo));
            }
            
            try
            {
                var xmlData = _proxy.queryObjectOut("02", _licenceKey, "02C06", string.Format(XmlCondition, sb));
                // 解析数据。
                var results = ParseXmlData(xmlData);

                // 装载数据。
                PrepareData(info, results);
            }
            catch (Exception)
            {
                info.WebServiceIsError = true;
            }
            return info;
        }

        /// <summary>
        /// 读取违法信息。
        /// </summary>
        /// <param name="identityNo">身份证号</param>
        /// <param name="archivesNo">档案编号</param>
        /// <returns></returns>
        public 交通违法信息 GetIllegalData(string identityNo, string archivesNo)
        {
            var info = new 交通违法信息();
            var sb = new StringBuilder();
            if (!string.IsNullOrEmpty(identityNo))
            {
                sb.Append(ToXmlField("sfzmmc", identityNo)); // 接口文档查询条件无身份证号查询，待定？
            }
            if (!string.IsNullOrEmpty(archivesNo))
            {
                sb.Append(ToXmlField("dabh", archivesNo));
            }

            try
            {
                // 参数说明：按接口文档，03为违法处理，04C01为查询违法基本信息接口标识。
                var xmlData = _proxy.queryObjectOut("03", _licenceKey, "04C01", string.Format(XmlCondition, sb));
                // 解析数据。
                var results = ParseXmlData(xmlData);

                // 装载数据。
                PrepareData(info, results);
            }
            catch (Exception)
            {
                info.WebServiceIsError = true;
            }
            return info;
        }

        /// <summary>
        /// 读取事件信息。
        /// </summary>
        /// <param name="identityNo"></param>
        /// <param name="archivesNo"></param>
        /// <returns></returns>
        public 交通事故信息 GetAccidentData(string identityNo, string archivesNo)
        {
            var info = new 交通事故信息();
            var sb = new StringBuilder();
            if (!string.IsNullOrEmpty(identityNo))
            {
                sb.Append(ToXmlField("sfzmmc", identityNo));
            }
            if (!string.IsNullOrEmpty(archivesNo))
            {
                sb.Append(ToXmlField("dabh", archivesNo));// 接口文档查询条件无档案编号查询，待定？
            }

            try
            {
                // 参数说明：按接口文档，04为事故处理，03C01为刑事案件事故信息接口标识。
                var xmlData = _proxy.queryObjectOut("04", _licenceKey, "03C01", string.Format(XmlCondition, sb));
                // 解析数据。
                var results = ParseXmlData(xmlData);

                // 装载数据。
                PrepareData(info, results);
            }
            catch (Exception)
            {
                info.WebServiceIsError = true;
            }
            return info;
        }

        /// <summary>
        /// 解析返回的Xml数据。
        /// </summary>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public List<RowResult> ParseXmlData(string xmlString)
        {
            var result = new List<RowResult>();
            var xmlDoc = new XmlDocument();
            try
            {
                // 先Url解码
                xmlDoc.LoadXml(HttpUtility.UrlDecode(xmlString));
            }
            catch (Exception)
            {
                return result;
            }
            var rootNode = xmlDoc.SelectSingleNode("root");
            if (rootNode != null)
            {
                var bodyNode = rootNode.SelectSingleNode("body");
                if (bodyNode != null)
                {
                    for (int i = 0; i <= bodyNode.ChildNodes.Count - 1; i++)
                    {
                        var rowNode = bodyNode.ChildNodes[i];
                        if (rowNode != null)
                        {
                            var dataRow = new RowResult();
                            if (rowNode.Attributes != null)
                            {
                                dataRow.Id = rowNode.Attributes["id"].Value;
                            }
                            for (int j = 0; j < rowNode.ChildNodes.Count; j++)
                            {
                                var fieldNode = rowNode.ChildNodes[j];
                                var fieldName = fieldNode.Name;
                                var fieldValue = fieldNode.InnerText;

                                dataRow.Fields.Add(new FieldResult { Name = fieldName, Value = fieldValue });
                            }
                            result.Add(dataRow);
                        }
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 装载数据。
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="results"></param>
        private void PrepareData(EntityBase entity, IEnumerable<RowResult> results)
        {
            foreach (var item in results)
            {
                var row = entity.NewRow();
                foreach (var field in item.Fields)
                {
                    if (entity.Columns.Contains(field.Name))
                    {
                        row[field.Name] = field.Value;
                    }
                }
                entity.Rows.Add(row);
            }
        }
    }
}